/*************************************************************************
 *
 *    Used with ICCARM and AARM.
 *
 *    (c) Copyright IAR Systems 2010
 *
 *    File name   : main.c
 *    Description : main module
 *
 *    History :
 *    1. Date        : January 15, 2010
 *       Author      : Stanimir Bonev
 *       Description : Create
 *
 *  This example project shows how to use the IAR Embedded Workbench for ARM
 * to develop code for the IAR KSK-i.MX25 board. It shows basic use
 * of I/O, system initialization (PLL, MAX, AIPI, EMI, MMU, AITC), timers
 * and UART1 (CN3). The example return echo on every received characher, LED0
 * indicate framing error, LED1 indicate overrun erro and LED2 indicate brake.
 *
 *  Terminal settings:
 *   Communication speed: 115200 bps
 *   Number of data bits:    8
 *   Number of stop bits:    1
 *   Parity:              none
 *
 *  Set the jumpers and the switches regarding the IAR KSK-i.MX25 User's Manual
 *
 *    $Revision: 39070 $
 *
 **************************************************************************/
#include <intrinsics.h>
#include <string.h>
#include <stdio.h>
#include "board.h"
#include "arm_comm.h"
#include "drv_asic.h"
#include "arm926ej_cp15_drv.h"
#include "ttbl.h"
#include "drv_i2c1.h"
#include "drv_MC34704.h"

static volatile Int32U Gpt1Counter;

char  Rx_Buffer[255];
char  Tx_Buffer[255];
Int8U  AT_Res[30];
Int8U  u2_flag = 0;

volatile Boolean FramingError;
volatile Boolean OverrunError;
volatile Boolean BreakDetect;

static Int32U secFlag = 0;


/*************************************************************************
 * Function Name: GPT1_Handler
 * Parameters: none
 *
 * Return: none
 *
 * Description: GPT1 interrupt handler
 *
 *************************************************************************/
static void toggle_LEDC6()
{
  if ( Gpt1Counter&0x1 ){
      LEDC6_ON();
  }else{
      LEDC6_OFF();           
  }  
}

static
void GPT1_Handler(void)
{
  // Clear interrupt flag
  GPT1SR_bit.OF1 = 1;
  ++Gpt1Counter; 
  secFlag = 1;//second flag
}

/*************************************************************************
 * Function Name: UART2_Handler
 * Parameters: none
 *
 * Return: none
 *
 * Description: UART interrupt handler
 *
 *************************************************************************/
Int8U count = 0;
void handle_rx2_data(char val)
{
  if(count == 0 && val != 0x02)return;
  Rx_Buffer[count++]=val;
  if(count == Rx_Buffer[2]+5){ count = 0; u2_flag = 1;}
}
static void UART2_Handler(void)
{
  // Errors
  char u2_temp_char;
  if(USR2_2_bit.BRCD){ // break
    USR2_2_bit.BRCD = 1;
    BreakDetect = TRUE;
  }
  if(USR1_2_bit.FRAMERR){ // framing error
    USR1_2_bit.FRAMERR = 1;
    FramingError = TRUE;
  }
  if(USR2_2_bit.ORE){  // overrun error
    USR2_2_bit.ORE = 0;
    OverrunError = TRUE;
  }  
  while(USR1_2_bit.RRDY) {
    u2_temp_char = URXD_2;
    handle_rx2_data(u2_temp_char);
  } 
  if(USR1_2_bit.AGTIM)
  { 
    USR1_2_bit.AGTIM = 1;

    // Pop remaing data from RX FIFO
    do
    {
      u2_temp_char = URXD_2;
      handle_rx2_data(u2_temp_char);
    }
    while(USR2_2_bit.RDR);
  }
  toggle_LEDC6();  
}
void uart2_putc(char);
Int8U at_count = 0;
void handle_Rx_msg(char val)
{
//  toggle_LEDC6();
  AT_Res[at_count++] = val;
  if(at_count == 30)at_count=0;
//  uart2_putc(val);  
}
/*************************************************************************
 * Function Name: UART4_Handler
 * Parameters: none
 *
 * Return: none
 *
 * Description: UART interrupt handler
 *
 *************************************************************************/
static void UART4_Handler(void)
{
  char temp_char;
  // Errors
  if(USR2_4_bit.BRCD){ // break
    USR2_4_bit.BRCD = 1;
    BreakDetect = TRUE;
  }
  if(USR1_4_bit.FRAMERR){ // framing error
    USR1_4_bit.FRAMERR = 1;
    FramingError = TRUE;
  }
  if(USR2_4_bit.ORE){  // overrun error
    USR2_4_bit.ORE = 0;
    OverrunError = TRUE;
  }  
  
  // receiver part
  if(USR1_4_bit.AGTIM)
  {
    USR1_4_bit.AGTIM = 1;
    // Pop remaing data from RX FIFO
    do
    {
      temp_char = URXD_4;
      handle_Rx_msg(temp_char); 
    }
    while(USR2_4_bit.RDR);
  }
  while(USR1_4_bit.RRDY) {   
      temp_char = URXD_4;
      handle_Rx_msg(temp_char); 
  } 
 
}

void uart2_putc(char a)
{
  while(!USR1_2_bit.TRDY);
  UTXD_2 = a;
}

void uart2_putstr(char *aPtr, int size)
{
  int count = 0;
  while( count++ < size ){
    uart2_putc(*aPtr++);
  }
}

void uart4_putc(char a)
{
  while(!USR1_4_bit.TRDY);
  UTXD_4 = a;
}

void uart4_putstr(char *aPtr)
{
  int count = 0, size = strlen(aPtr);
  while( count++ < size ){
    uart4_putc(*aPtr++);
  }
}
Int8U calcEcc(char* pStr, Int8U length)
{
  Int8U count,EccValue=0;
  for(count = 0; count < length; count ++)
    EccValue ^= *(pStr+count);
  return EccValue;
}
int process_cmd(Int8U tx_length, Int8U *rx_length)
{
  uart2_putc(0x02);
  uart2_putc((tx_length>>8) &0xff);
  uart2_putc(tx_length & 0xff);
  uart2_putstr(Tx_Buffer,tx_length);
  uart2_putc(calcEcc(Tx_Buffer,tx_length));
  uart2_putc(0x03);
  while(!u2_flag);
  u2_flag = 0;
  *rx_length = Rx_Buffer[2]+5;
  return 0;
}



int bell_control()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0x31;
  Tx_Buffer[1] = 0x13;
  Tx_Buffer[2] = 0x01;
  Tx_Buffer[3] = 0x00;
  Tx_Buffer[4] = 0x1;
  ret = process_cmd(5, &rx_length);
  if(!ret && rx_length == 7 && Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
    return 0;
  }
  else return -1;
}
int led_control(Int8U led_bit)
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0x31;
  Tx_Buffer[1] = 0x14;
  Tx_Buffer[2] = led_bit<<6;
  ret = process_cmd(3, &rx_length);
  if(!ret && rx_length == 7 && Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
    return 0;
  }
  else return -1;
}
int open_rf()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0x31;
  Tx_Buffer[1] = 0x90;
  ret = process_cmd(2, &rx_length);
  if(!ret && rx_length == 7 && Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
    return 0;
  }
  else return -1;
}
int close_rf()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0x31;
  Tx_Buffer[1] = 0x91;
  ret = process_cmd(2, &rx_length);
  if(!ret && rx_length == 7 && Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
    return 0;
  }
  else return -1;
}
void SendSMS(char *p);
void gprs_send_data(char *p);
int active_card()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0x32;
  Tx_Buffer[1] = 0x24;
  Tx_Buffer[2] = 0xff;
  Tx_Buffer[3] = 0xff;
  ret = process_cmd(4, &rx_length);
  if(!ret && /*rx_length == 7 && */Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
/*    Int8U i,temp;
    for(i=0;i<rx_length;i++)
      temp = Rx_Buffer[i];*/
    char p[70];
    unsigned char tmp1[30],tmp2[30];
    memset(p,0,sizeof(p));
    memset(tmp1,0,sizeof(tmp1));
    memset(tmp2,0,sizeof(tmp2));
    memcpy(tmp1,Rx_Buffer+7,Rx_Buffer[6]);
    memcpy(tmp2,Rx_Buffer+8+Rx_Buffer[6],Rx_Buffer[7+Rx_Buffer[6]]);
    sprintf(p," Type:B UID:%x%x%x ATRdata:%x%x%x%x%x%x%x%x\r\n",tmp1[1],tmp1[2],tmp1[3],tmp2[0],tmp2[1],tmp2[2],tmp2[3],tmp2[4],tmp2[5],tmp2[6],tmp2[7]);    
    bell_control();
    gprs_send_data(p);
//    SendSMS(p);
    return 0;
  }
  else return -1;
}
int power_on_card()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0x32;
  Tx_Buffer[1] = 0x22;
  Tx_Buffer[2] = 0x00;
  Tx_Buffer[3] = 0x00;
  Tx_Buffer[4] = 0x11;
  ret = process_cmd(5, &rx_length);
  if(!ret && /*rx_length == 7 && */Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
  /*  Int8U i,temp;
    for(i=0;i<rx_length;i++)
      temp = Rx_Buffer[i];*/
    return 0;
  }
  else return -1;
}
int read_aid()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0xc0;
  Tx_Buffer[1] = 0x24;
  Tx_Buffer[2] = 0xB2;
  ret = process_cmd(3, &rx_length);
  if(!ret && /*rx_length == 7 && */Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
    return 0;
  }
  else return -1;
}
int terminal_init()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0xc1;
  Tx_Buffer[1] = 0xf4;
  Tx_Buffer[2] = 0x11;
  ret = process_cmd(3, &rx_length);
  if(!ret && /*rx_length == 7 && */Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
    return 0;
  }
  else return -1;
}
int trade_init()
{
  Int8U rx_length = 0, ret;
  memset(Tx_Buffer,0,sizeof(Tx_Buffer));
  memset(Rx_Buffer,0,sizeof(Rx_Buffer));
  Tx_Buffer[0] = 0xc1;
  Tx_Buffer[1] = 0xf0;
  Tx_Buffer[2] = 0x01;
  ret = process_cmd(3, &rx_length);
  if(!ret && /*rx_length == 7 && */Rx_Buffer[3] == 0x00 && Rx_Buffer[4] == 0x00)
  {
    return 0;
  }
  else return -1;
}
void SendSMS(char *p)
{
  Int32U curTime = Gpt1Counter;
  while(Gpt1Counter<=curTime+3); 
  uart4_putstr("AT+CGCLASS=\"CC\"\r");
  while(Gpt1Counter<=curTime+6);
  uart4_putstr("AT+CREG?\r");
  while(Gpt1Counter<=curTime+7);
  uart4_putstr("AT+CSQ\r"); 
  while(Gpt1Counter<=curTime+8);
  uart4_putstr("AT+CMGF=1\r");
  while(Gpt1Counter<=curTime+9);
  uart4_putstr("AT+CMGS=\"+8615801939599\"\r");
  while(Gpt1Counter<=curTime+10);
  uart4_putstr(p);
  uart4_putc(0x1a);
}
void delay(int n)
{
  for(int j=0;j<(n<<6);j++)
  {
    for(int i=0;i<50000;i++);
  }
}
void waitAtRes()
{
  delay(10);
  uart4_putstr("\r");
  memset(AT_Res,0,30);
  at_count = 0;
  while(AT_Res[3]!='O' || AT_Res[4]!='K');
}
void gprs_init()
{
  Int32U curTime = Gpt1Counter;
  while(Gpt1Counter<=curTime+3);
  uart4_putstr("AT+CGCLASS=\"CG\"\r");
  delay(20);
  uart4_putstr("AT+WOPEN=1\r");
  delay(20);
  uart4_putstr("AT+WIPCFG=1\r");
  delay(10);
  uart4_putstr("AT+WIPBR=1,6\r"); 
  delay(10);
  uart4_putstr("AT+WIPBR=2,6,11,\"CMNET\"\r");
  delay(10);
  uart4_putstr("AT+WIPBR=3,6,15\r");
  delay(10);
  uart4_putstr("AT+WIPBR=4,6,0");
  waitAtRes();
  led_control(0x3);
  uart4_putstr("AT+WIPBR=3,6,15\r");
  delay(10);
  
  uart4_putstr("AT+WIPCREATE=2,1,\"58.41.209.197\",3333");
  waitAtRes();
  uart4_putstr("AT+WIPDATA=2,1,1\r");
  delay(10);
  
  //uart4_putstr("start transfer data\r\n");
  //delay(20);
}
void gprs_send_data(char *p)
{
/*  uart4_putstr("AT+WIPCREATE=2,1,\"58.41.209.197\",3333");
  waitAtRes();
  uart4_putstr("AT+WIPDATA=2,1,1\r");
  delay(10);*/
  while(Gpt1Counter<1);
  uart4_putstr(p);
  delay(5);
  Gpt1Counter = 0;
/*  uart4_putstr("+++");
  delay(20);
  uart4_putstr("AT+WIPCLOSE=2,1\r"); 
  delay(10);*/
}
void gprs_end()
{
  uart4_putstr("AT+WIPBR=5,6\r"); 
}
/*************************************************************************
 * Function Name: main
 * Parameters: none
 *
 * Return: none
 *
 * Description:
 *
 *************************************************************************/
int main(void)
{
  // Init MMU
  CP15_Mmu(FALSE);            // Disable MMU
  // Privileged permissions  User permissions AP
  // Read-only               Read-only        0
  CP15_SysProt(FALSE);
  CP15_RomProt(TRUE);
  CP15_InitMmuTtb(TtSB,TtTB); // Build L1 and L2 Translation tables
  CP15_SetTtb(L1Table);       // Set base address of the L1 Translation table
  CP15_SetDomain( (DomainManager << 2*1) | (DomainClient << 0)); // Set domains
  CP15_Mmu(TRUE);             // Enable MMU
  CP15_Cache(TRUE);           // Enable ICache,DCache
  
  //GPIO Init 
  IOMUXC_SW_MUX_CTL_PAD_FEC_MDIO_bit.MUX_MODE = ALT5_MUX_MODE;
  IOMUXC_SW_MUX_CTL_CSI_D8_bit.MUX_MODE = ALT5_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_SD1_DATA2_bit.MUX_MODE = ALT5_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_SD1_DATA3_bit.MUX_MODE = ALT5_MUX_MODE;
 
  LEDC_PORT |= LEDC_MASK;
  LEDC_DIR  |= LEDC_MASK;  
  LEDB_PORT |= LEDB_MASK;
  LEDB_DIR  |= LEDB_MASK;    
  LEDA_PORT |= LEDA_MASK;
  LEDA_DIR  |= LEDA_MASK;   

  LEDC6_OFF();//LED
  CELL_PWR_ON();//CELL ON
  ANT_BSC_SEL_OFF();
  ANT_CELL_SEL_ON();//RF switch sel CELL
  // Init AITC
  ASIC_Init();
  
  // Init GTIM
  // Enable GPT1 clock
  CGCR0_bit.ipg_per_gpt  = 1;
  CGCR1_bit.ipg_clk_gpt1 = 1;

  // Disable timer
  GPT1CR = 0;
  // Disable interrupt
  GPT1IR_bit.OF1IE = 0;
  // Reset Timer1
  GPT1CR_bit.SWR = 1;
  while(GPT1CR_bit.SWR);
  // ipg_clk_highfreq - PERCLK5
  GPT1CR_bit.CLKSRC= 2;
  // reset counters
  GPT1CR_bit.ENMOD = 1;
  // Restart counter
  GPT1CR_bit.FRR = 0;

  // Init the Timer's period
  GPT1PR_bit.PRESCALER = 0;
  GPT1OCR1 = HCLK / ((PCDR1_bit.PERDIV5+1) * GPT1_TICK_PER_SEC);// 1 sec timer
  // Init GPT1 interrupt
  ASIC_SetupIntr(GPT1_Handler,FALSE,INT_GPT1,1);
  ASIC_EnableIntSource(INT_GPT1);
  // Enable GPT1
  GPT1CR_bit.EN = 1;
  // Enable Oput compare 1 interrupt
  GPT1IR_bit.OF1IE = 1;

  // I2C1_Init();

  // UART Init
  // Enable UART1 clock
  CGCR0_bit.ipg_per_uart  = 1;
  CGCR2_bit.ipg_clk_uart2 = 1;
  CGCR2_bit.ipg_clk_uart4 = 1;

  UCR2_2_bit.SRST = 0;
  while(!UCR2_2_bit.SRST);
  UCR1_2_bit.RRDYEN = 1;    // Receiver Ready Interrupt Enable
  UCR2_2_bit.RXEN = 1;      // receiver enable
  UCR2_2_bit.TXEN = 1;      // Transmitter enable
  UCR2_2_bit.ATEN = 1;      // Aging Timer Enable
  UCR2_2_bit.WS = 1;        // 8 bits word
  UCR2_2_bit.STPB = 0;      // 1 stop bit
  UCR2_2_bit.PREN = 0;      // no parity
  UCR2_2_bit.IRTS = 1;      // flowcontrol disable
  UCR3_2_bit.RXDMUXSEL = 1; // RXD Muxed Input Selected
  UCR3_2_bit.FRAERREN = 1;  // enable framing error
  UCR4_2_bit.OREN = 1;      // enable overrun error
  UCR4_2_bit.BKEN = 1;      // enable break condition detection interrupt
  UFCR_2_bit.RXTL = 30;      // RxFIFO has 30 character
  UFCR_2_bit.TXTL = 2;      // TxFIFO has 2 or fewer characters
  UFCR_2_bit.RFDIV = 5;     // Divide input clock by 1
  UFCR_2_bit.DCEDTE = 0;    // Select data communication equipment (DCE)

  ONEMS_2 =  HCLK /((PCDR3_bit.PERDIV15+1) + 1000);
  UBIR_2 = 576-1;//57600
  UBMR_2 = 41562-1;
  USR1_2 = 0xFFFFFFFF;      // clear pending interrupts
  USR2_2 = 0xFFFFFFFF;      // clear pending interrupts
  
  


  UCR2_4_bit.SRST = 0;
  while(!UCR2_4_bit.SRST);
  UCR1_4_bit.RRDYEN = 1;    // Receiver Ready Interrupt Enable
  UCR2_4_bit.RXEN = 1;      // receiver enable
  UCR2_4_bit.TXEN = 1;      // Transmitter enable
  UCR2_4_bit.ATEN = 1;      // Aging Timer Enable
  UCR2_4_bit.WS = 1;        // 8 bits word
  UCR2_4_bit.STPB = 0;      // 1 stop bit
  UCR2_4_bit.PREN = 0;      // no parity
  UCR2_4_bit.IRTS = 0;      // flowcontrol enable
  UCR2_4_bit.CTS = 1;      // flowcontrol enable
  UCR2_4_bit.CTSC = 0;      // flowcontrol enable
  UCR3_4_bit.RXDMUXSEL = 1; // RXD Muxed Input Selected
  UCR3_4_bit.FRAERREN = 1;  // enable framing error
  UCR4_4_bit.OREN = 0;      // enable overrun error
  UCR4_4_bit.BKEN = 1;      // enable break condition detection interrupt
  UFCR_4_bit.RXTL = 10;      // RxFIFO has 1 character
  UFCR_4_bit.TXTL = 2;      // TxFIFO has 2 or fewer characters
  UFCR_4_bit.RFDIV = 5;     // Divide input clock by 1
  UFCR_4_bit.DCEDTE = 0;    // Select data communication equipment (DCE)

  ONEMS_4 =  HCLK /((PCDR3_bit.PERDIV15+1) + 1000);
  UBIR_4 = 1152-1;
  UBMR_4 = 41562-1;
  USR1_4 = 0xFFFFFFFF;      // clear pending interrupts
  USR2_4 = 0xFFFFFFFF;      // clear pending interrupts
  
//  UTS_4_bit.LOOP = 1; // LOOPBACK Test
  //UART4
  
  IOMUXC_SW_MUX_CTL_PAD_KPP_COL0_bit.MUX_MODE = ALT1_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_KPP_COL1_bit.MUX_MODE = ALT1_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_KPP_COL2_bit.MUX_MODE = ALT1_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_KPP_COL3_bit.MUX_MODE = ALT1_MUX_MODE;
  //UART 2
  
  IOMUXC_SW_MUX_CTL_PAD_UART2_RXD_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_TXD_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_RTS_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_CTS_bit.MUX_MODE = ALT0_MUX_MODE;  
  // Init UART2 interrupt
  ASIC_SetupIntr(UART2_Handler,FALSE,INT_UART2,1);
  ASIC_EnableIntSource(INT_UART2);
  // Init UART4 interrupt
  ASIC_SetupIntr(UART4_Handler,FALSE,INT_UART4,1);
  ASIC_EnableIntSource(INT_UART4);

  UCR1_2_bit.UARTEN = 1;    // enable UART
  UCR1_4_bit.UARTEN = 1;    // enable UART


  // Enable interrupts
  ASIC_EnableIRQ();
  ASIC_EnableFIQ();
  __enable_interrupt();

  Gpt1Counter= 0;

//  bell_control();
  led_control(0x1);
  gprs_init();
//  open_rf();
  power_on_card();
//  active_card();
//  read_aid();
//  terminal_init();
//  trade_init();
//  close_rf();
//  SendSMS("hello");
  /*
  gprs_init();
  gprs_send_data(" cangyi,yeah!\r\n");
  gprs_send_data(" hello,cangyi!\r\n");
  gprs_end();*/
  
  while(1){
        // transmitter part
    if (secFlag == 1){
        toggle_LEDC6();
        secFlag = 0;
        if(Gpt1Counter > 1000)Gpt1Counter=0;
   }
   active_card();
  };
}
  